#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<assert.h>
#include<string.h>
#define NUM 10

typedef void (*func_t)(); //函数指针

func_t handlerTask[NUM];//函数指针数组

//样例任务
void task1()
{
  printf("handler task1\n");
}
void task2()
{
  printf("handler task2\n");
}
void task3()
{
  printf("handler task3\n");
}

void loadTask()
{
  memset(handlerTask,0,sizeof(handlerTask));
  handlerTask[0] = task1;
  handlerTask[1] = task2;
  handlerTask[2] = task3;
}
//阻塞 vs 非阻塞
//1.阻塞：一直等待子进程退出
//2.检测子进程状态，如果没有就绪，直接返回  --- 每一次都是一次非阻塞等待 -- 多次非阻塞等待 -- 轮询



//非阻塞状态好处：不会占用父进程的所有精力，可以在轮询期间，干干别的！
int main()
{
  pid_t id = fork();
  assert(id != -1);

  if(id == 0)
  {
    //子进程
    int cnt = 5;
    while(cnt)
    {
      printf("我是一个子进程！pid:%d,ppid:%d,cnt:%d\n",getpid(),getppid(),cnt--);
      sleep(1);
    }
    exit(20);
  }
  //parent
  
  loadTask();
  int status = 0;
  while(1)
  {
      pid_t ret = waitpid(id,&status,WNOHANG);//WNOHANG: 非阻塞-> 子进程没有退出，父进程检测完毕，立刻返回
       if(ret == 0)
       {
         //子进程没有退出，我的waitpid没有等待失败，仅仅是检测到了子进程没退出
         //TODO
         printf("wait done,but child process running......,parent running other things\n");
         for(int i = 0; handlerTask[i] != NULL;i++)
         {
           handlerTask[i]();//采用回调的方式，执行我们想让父进程在空闲的时候做的事情
         }
       }
       else if(ret >0)
       {
         //waitpid调用成功 && 子进程退出了
         printf("wait sucesss, sig number:%d,exit code:%d\n",(status>>8) & 0xFF,(status & 0x7F));
         break;
       }
       else
       {
         //waitpid调用失败
         printf("waitpid call failed\n");//比如说wait(id+1,....);
         break;
       }
     sleep(1); 
  }
} 

